home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Games / Arashi 1.1.1 / source code / Game Source / GameCompiler (jam) / Parser.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-21  |  19.8 KB  |  964 lines  |  [TEXT/KAHL]

  1. /*/
  2.      Project Arashi: Parser.c
  3.      Major release: Version 1.1d2, 9/5/95
  4.  
  5.      Last modification: Tuesday, November 22, 1994, 0:23
  6.      Created: Wednesday, February 10, 1993, 19:18
  7.  
  8.      Copyright © 1993-1994, Juri Munkki
  9. /*/
  10.  
  11. #include "Numbers.h"
  12. #include "Parser.h"
  13. #include "RAMFiles.h"
  14. #include "CStringDictionary.h"
  15. #include "CTagBase.h"
  16. #include <math.h>
  17. #include "InternalVars.h"
  18.  
  19.  
  20. #ifdef    DEBUGPARSER
  21. #include "stdio.h"
  22. #define    DEBUGPAR(a)    {    a    }
  23. #else
  24. #define    DEBUGPAR(a)    {        }
  25. #endif
  26.  
  27. ParserVariables    parserVar;
  28. long            lastKeyword;
  29. long            lastVariable;
  30.  
  31. typedef    struct
  32. {
  33.     double    value;
  34.     short    calcLevel;
  35. } variableValue;
  36.  
  37. Handle                theScript;
  38. double                *stackP;
  39. CStringDictionary    *symTable;
  40. CTagBase            *variableBase;
  41. CTagBase            *programBase;
  42. short                currentLevel = 0;
  43. short                fromLevel = 32000;
  44. short                upToLevel = -1;
  45.  
  46. void    InitSymbols()
  47. {
  48.     symTable = new CStringDictionary;
  49.     symTable->IStringDictionary();
  50.     
  51.     symTable->AddDictEntry("\pmin",-1);
  52.     symTable->AddDictEntry("\pmax",-1);
  53.     symTable->AddDictEntry("\prandom",-1);
  54.     symTable->AddDictEntry("\psin",-1);
  55.     symTable->AddDictEntry("\pcos",-1);
  56.     symTable->AddDictEntry("\pint",-1);
  57.     symTable->AddDictEntry("\pround",-1);
  58.     lastKeyword = symTable->AddDictEntry("\plevel",-1);
  59.     lastVariable = lastKeyword;
  60.     
  61.     variableBase = new CTagBase;
  62.     variableBase->ITagBase();
  63.     
  64.     programBase = new CTagBase;
  65.     programBase->ITagBase();
  66. }
  67.  
  68. void    ResetVariables()
  69. {
  70.     symTable->Dispose();
  71.     variableBase->Dispose();
  72.     programBase->Dispose();
  73.     InitSymbols();
  74. }
  75. void    CreateVariable(
  76.     long    token)
  77. {
  78.     variableValue    zeroValue;
  79.     
  80.     zeroValue.value = 0;
  81.     zeroValue.calcLevel = -1;
  82.     variableBase->WriteEntry(token, sizeof(variableValue), &zeroValue);
  83. }
  84.  
  85. void    VariableToKeyword(
  86.     LexSymbol    *theSymbol)
  87. {
  88.     switch(theSymbol->value.token)
  89.     {
  90.         case kMinKey:
  91.             theSymbol->kind = kLexMin;
  92.             break;
  93.         case kMaxKey:
  94.             theSymbol->kind = kLexMax;
  95.             break;
  96.         case kRandomKey:
  97.             theSymbol->kind = kLexFun0;
  98.             break;
  99.         case kSinKey:
  100.         case kCosKey:
  101.         case kIntKey:
  102.         case kRoundKey:
  103.             theSymbol->kind = kLexFun1;
  104.             break;
  105.         case kLevelKey:
  106.             theSymbol->kind = kLexLevel;
  107.             break;
  108.     }
  109. }
  110.  
  111. short    MatchVariable(
  112.     StringPtr    theString)
  113. {
  114.     unsigned    char theChar;
  115.     short    matchCount = 0;
  116.     short    state = TRUE;
  117.     
  118.     theChar = theString[0];
  119.     
  120.     if(    (theChar >= 'a' && theChar <= 'z') ||
  121.         (theChar >= 'A' && theChar <= 'Z'))
  122.     {    
  123.         matchCount++;
  124.         
  125.         do
  126.         {
  127.             theChar = theString[matchCount];
  128.             
  129.             if(    (theChar >= 'a' && theChar <= '}') || theChar == '_' ||
  130.                 (theChar >= 'A' && theChar <= ']') || theChar == '.' ||
  131.                 (theChar >= '0' && theChar <= '9'))
  132.             {
  133.                 matchCount++;
  134.             }
  135.             else
  136.             {
  137.                 state = FALSE;
  138.             }
  139.         } while(state);
  140.     }
  141.     
  142.     return matchCount;
  143. }
  144. /*
  145. **    Match the exponent part of a floating point number.
  146. **    The input is a null-terminated string. The output
  147. **    tells how many characters could belong to the exponent
  148. **    of a floating point number.
  149. */
  150. short    MatchExponent(
  151.     StringPtr    theString)
  152. {
  153.     enum    {    initialState,
  154.                 integerState,
  155.                 endState    };
  156.  
  157.     short    matchCount = 0;
  158.     char    theChar;
  159.     short    state = initialState;
  160.  
  161.     while(state != endState)
  162.     {    theChar = theString[matchCount];
  163.         
  164.         if(theChar == 0)
  165.             state = endState;    //    String ends with null
  166.  
  167.         switch(state)
  168.         {    case initialState:
  169.                 if(    theChar == '+'    ||    theChar == '-'    ||
  170.                     (theChar >= '0' && theChar <= '9'))
  171.                 {        matchCount++;
  172.                         state = integerState;
  173.                 }
  174.                 else    state = endState;
  175.                 break;
  176.             case integerState:
  177.                 if(theChar >= '0' && theChar <= '9')
  178.                 {    matchCount++;
  179.                 }
  180.                 else    state = endState;
  181.                 break;                
  182.         }
  183.     }
  184.  
  185.     return matchCount;
  186. }
  187.  
  188. /*
  189. **    Match the number part of a row index.
  190. **    The input is a null-terminated string. The output
  191. **    tells how many characters could belong to the row
  192. **    index of a row specifier. Row specifiers are of the
  193. **    format @n, where n is an integer. (@1, @2, @3, ...)
  194. */
  195. short    MatchRowIndex(
  196.     StringPtr    theString)
  197. {
  198.     short    matchCount = 0;
  199.     char    theChar;
  200.  
  201.     theChar = *theString++;
  202.  
  203.     while(theChar >= '0' && theChar <= '9')
  204.     {    matchCount++;
  205.         theChar = *theString++;
  206.     }
  207.  
  208.     return matchCount;
  209. }
  210.  
  211. /*
  212. **    Match a floating point number.
  213. **    The input is a null-terminated string. The output
  214. **    tells how many characters could belong to a floating
  215. **    point number.
  216. */
  217. short    MatchFloat(
  218.     StringPtr    theString)
  219. {
  220.     enum    {    initialState,
  221.                 integerPartState,
  222.                 decimalPartState,
  223.                 exponentMatchState,
  224.                 endState    };
  225.  
  226.     short    matchCount = 0;
  227.     char    theChar;
  228.     short    state = initialState;
  229.  
  230.     while(state != endState)
  231.     {    theChar = theString[matchCount];
  232.         
  233.         if(theChar == 0)
  234.             state = endState;    //    String ends with null
  235.  
  236.         switch(state)
  237.         {    case initialState:
  238.                 if(    theChar == '+'    ||    theChar == '-'    ||
  239.                     (theChar >= '0' && theChar <= '9'))
  240.                 {        matchCount++;
  241.                         state = integerPartState; 
  242.                 }
  243. #ifdef ALLOWSHORTHAND        //    Are numbers like . and .0 and .e1 and .0e1 valid?
  244.                 else if(theChar == '.')
  245.                 {    matchCount++;
  246.                     state = decimalPartState;
  247.                 }
  248. #endif
  249.                 else    state = endState;
  250.                 break;
  251.  
  252.             case integerPartState:
  253.                 if(theChar >= '0' && theChar <= '9')
  254.                 {    matchCount++;
  255.                 }
  256.                 else if(theChar == 'e' || theChar == 'E')
  257.                 {    state = exponentMatchState;
  258.                 }
  259.                 else if(theChar == '.')
  260.                 {    matchCount++;
  261.                     state = decimalPartState;
  262.                 }
  263.                 else    state = endState;
  264.                 break;
  265.  
  266.             case decimalPartState:
  267.                 if(theChar >= '0' && theChar <= '9')
  268.                 {    matchCount++;
  269.                 }
  270.                 else if(theChar == 'e' || theChar == 'E')
  271.                 {    state = exponentMatchState;
  272.                 }
  273.                 else    state = endState;
  274.                 break;                
  275.  
  276.             case exponentMatchState:
  277.                 {
  278.                     short    expLength = MatchExponent(theString+matchCount+1);
  279.                 
  280.                     if(expLength > 0)
  281.                     {    matchCount += expLength+1;
  282.                     }
  283.                     state = endState;
  284.                 }
  285.                 break;
  286.         }
  287.     }
  288.     
  289.     return matchCount;
  290. }
  291.  
  292.  
  293. void    EmitInstruction(
  294.     LexSymbol    *theOperation,
  295.     short        stackChange)
  296. {
  297.     long    writeOffset = parserVar.logicalSize;
  298.  
  299.     parserVar.stackDepth += stackChange;
  300.     if(parserVar.stackDepth > parserVar.stackMax)
  301.         parserVar.stackMax = parserVar.stackDepth;
  302.  
  303.     if(    IncreaseByClump(    parserVar.output,
  304.                             &parserVar.realSize,
  305.                             &parserVar.logicalSize,
  306.                             sizeof(LexSymbol),
  307.                             sizeof(LexSymbol)*10) == noErr)
  308.     {    *(LexSymbol *)(*parserVar.output+writeOffset) = *theOperation;
  309.     }
  310. }
  311.  
  312. void    SkipComment()
  313. {
  314.     parserVar.input+= 2;
  315.     if(parserVar.input[0] != 0)
  316.     {    while(    (parserVar.input[0] != 0) &&
  317.                 !(parserVar.input[0] == '*' && parserVar.input[1] == '/'))
  318.         {    parserVar.input++;
  319.         }
  320.         
  321.         if(parserVar.input[0] != 0)
  322.         {    parserVar.input += 2;
  323.         }
  324.     }
  325. }
  326. void    SkipOneLineComment()
  327. {
  328.     parserVar.input+= 2;
  329.     if(parserVar.input[0] != 0)
  330.     {    while(    (parserVar.input[0] != 0) &&
  331.                 !(parserVar.input[0] == 13))
  332.         {    parserVar.input++;
  333.         }
  334.         
  335.         if(parserVar.input[0] != 0)
  336.         {    parserVar.input += 1;
  337.         }
  338.     }
  339. }
  340.  
  341. void    LexRead(
  342.     LexSymbol    *theSymbol)
  343. {
  344.     unsigned char    theChar;
  345.     short            matchCount;
  346.  
  347.     //    First, skip any whitespace like returns, tabs, spaces and control characters.
  348.     
  349.     theChar = *parserVar.input;
  350.     
  351.     while(theChar <= 32 && theChar > 0)
  352.     {    theChar = *(++parserVar.input);
  353.     }
  354.     
  355.     switch(theChar)
  356.     {
  357.         case '+':
  358.             theSymbol->kind = kLexPlus;
  359.             parserVar.input++;
  360.             break;
  361.         case '-':
  362.             theSymbol->kind = kLexMinus;
  363.             parserVar.input++;
  364.             break;
  365.         case '|':
  366.             theSymbol->kind = kLexAbs;
  367.             parserVar.input++;
  368.             break;
  369.         case '*':
  370.             theSymbol->kind = kLexMultiply;
  371.             parserVar.input++;
  372.             break;
  373.         case '/':
  374.             if(parserVar.input[1] == '*')
  375.             {    SkipComment();
  376.                 LexRead(theSymbol);
  377.             }
  378.             else if(parserVar.input[1] == '/')
  379.             {    SkipOneLineComment();
  380.                 LexRead(theSymbol);
  381.             }
  382.             else
  383.             {    theSymbol->kind = kLexDivide;
  384.                 parserVar.input++;
  385.             }
  386.             break;
  387.         case '%':
  388.             theSymbol->kind = kLexModulo;
  389.             parserVar.input++;
  390.             break;
  391.         case '^':
  392.             theSymbol->kind = kLexPower;
  393.             parserVar.input++;
  394.             break;
  395.         case '>':
  396.             theSymbol->kind = kLexGt;
  397.             parserVar.input++;
  398.             break;
  399.         case '<':
  400.             theSymbol->kind = kLexLt;
  401.             parserVar.input++;
  402.             break;
  403.         case '=':
  404.             theSymbol->kind = kLexEq;
  405.             parserVar.input++;
  406.             break;
  407. #ifdef TESTMINMAX
  408.         case ']':
  409.             theSymbol->kind = kLexMin;
  410.             parserVar.input++;
  411.             break;
  412.         case '[':
  413.             theSymbol->kind = kLexMax;
  414.             parserVar.input++;
  415.             break;
  416. #endif
  417.         case '(':
  418.             theSymbol->kind = kLexOpenParen;
  419.             parserVar.input++;
  420.             break;
  421.         case ')':
  422.             theSymbol->kind = kLexCloseParen;
  423.             parserVar.input++;
  424.             break;
  425.         case 0:
  426.             theSymbol->kind = kLexEof;
  427.             break;
  428.         default:
  429.             matchCount = MatchVariable(parserVar.input);
  430.             if(matchCount > 0)
  431.             {    theSymbol->value.token = symTable->FindEntry(parserVar.input - 1, matchCount);
  432.                 if(theSymbol->value.token > lastVariable)
  433.                 {    lastVariable = theSymbol->value.token;
  434.                     CreateVariable(lastVariable);
  435.                 }
  436.                 theSymbol->kind = kLexVariable;
  437.                 if(theSymbol->value.token <= lastKeyword)
  438.                 {    VariableToKeyword(theSymbol);
  439.                 }
  440.                 parserVar.input += matchCount;
  441.             }
  442.             else
  443.             {    matchCount = MatchFloat(parserVar.input);
  444.                 if(matchCount > 0)
  445.                 {    char    temp;
  446.                 
  447.                     temp = parserVar.input[-1];
  448.                     parserVar.input[-1] = matchCount;
  449.                     theSymbol->kind = kLexConstant;
  450.                     theSymbol->value.floating = StringToLongDouble(parserVar.input-1);
  451.                     parserVar.input[-1] = temp;
  452.                     parserVar.input += matchCount;
  453.                 }
  454.             }
  455.             
  456.             if(matchCount == 0)
  457.             {    theSymbol->kind = kParseError;
  458.             }
  459.             break;
  460.     }
  461. }
  462.  
  463. void    LexMatch(
  464.     short kind)
  465. {
  466.     if(parserVar.lookahead.kind == kind)
  467.         LexRead(&parserVar.lookahead);
  468.     else
  469.         parserVar.lookahead.kind = kParseError;
  470. }
  471.  
  472.  
  473. void    ParseFactor()
  474. {
  475.     LexSymbol    savedSymbol;
  476.     
  477.     switch(parserVar.lookahead.kind)
  478.     {    
  479.         case kLexFun0:
  480.             EmitInstruction(&parserVar.lookahead,1);
  481.             DEBUGPAR(printf("function0 ");)
  482.             LexMatch(parserVar.lookahead.kind);
  483.             break;
  484.             
  485.         case kLexFun1:
  486.             savedSymbol = parserVar.lookahead;
  487.             LexMatch(parserVar.lookahead.kind);
  488.             ParseFactor();
  489.             EmitInstruction(&savedSymbol, 0);
  490.             DEBUGPAR(printf("function1 ");)
  491.             break;
  492.  
  493.         case kLexConstant:
  494.             EmitInstruction(&parserVar.lookahead,1);
  495.             DEBUGPAR(printf("%3.2f ", parserVar.lookahead.value.floating);)
  496.             LexMatch(parserVar.lookahead.kind);
  497.             break;
  498.             
  499.         case kLexVariable:
  500.             EmitInstruction(&parserVar.lookahead,1);
  501.             DEBUGPAR(printf("Variable #%ld ", parserVar.lookahead.value.token);)
  502.             LexMatch(parserVar.lookahead.kind);
  503.             break;
  504.             
  505.         case kLexRowOffset:
  506.             EmitInstruction(&parserVar.lookahead,1);
  507.             DEBUGPAR(printf("@(%ld) ", parserVar.lookahead.value.offset);)
  508.             LexMatch(parserVar.lookahead.kind);
  509.             break;
  510.         
  511.         case kLexMinus:
  512.             LexMatch(parserVar.lookahead.kind);
  513.             ParseFactor();
  514.             
  515.             savedSymbol.kind = kUnaryMinus;
  516.             EmitInstruction(&savedSymbol,0);
  517.             DEBUGPAR(printf("neg ");)
  518.             break;
  519.  
  520.         case kLexAbs:
  521.             LexMatch(parserVar.lookahead.kind);
  522.             ParseFactor();
  523.  
  524.             savedSymbol.kind = kLexAbs;
  525.             EmitInstruction(&savedSymbol,0);
  526.             DEBUGPAR(printf("abs ");)
  527.             break;
  528.  
  529.         case kLexPlus:    //    This is a no-op.
  530.             LexMatch(parserVar.lookahead.kind);
  531.             ParseFactor();
  532.             break;
  533.         
  534.         case kLexOpenParen:
  535.             LexMatch(parserVar.lookahead.kind);
  536.             ParseCompare();
  537.             if(parserVar.lookahead.kind == kLexCloseParen)
  538.             {    LexMatch(parserVar.lookahead.kind);
  539.             }
  540.             else
  541.             {    parserVar.lookahead.kind = kParseError;
  542.             }
  543.             break;
  544.  
  545.         default:
  546.             parserVar.lookahead.kind = kParseError;
  547.             break;
  548.     }
  549. }
  550. void    ParsePower()
  551. {
  552.     LexSymbol    mySymbol;
  553.     
  554.     ParseFactor();
  555.     
  556.     while(parserVar.lookahead.kind == kLexPower)
  557.     {    mySymbol.kind = parserVar.lookahead.kind;
  558.  
  559.         LexMatch(parserVar.lookahead.kind);
  560.         ParseFactor();
  561.     
  562.         EmitInstruction(&mySymbol,-1);
  563.  
  564.         DEBUGPAR(printf("^ ");)
  565.     }
  566. }
  567. void    ParseTerm()
  568. {
  569.     LexSymbol    mySymbol;
  570.     
  571.     ParsePower();
  572.     
  573.     while(parserVar.lookahead.kind == kLexMultiply ||
  574.             parserVar.lookahead.kind == kLexDivide ||
  575.             parserVar.lookahead.kind == kLexModulo)
  576.     {    mySymbol.kind = parserVar.lookahead.kind;
  577.  
  578.         LexMatch(parserVar.lookahead.kind);
  579.         ParsePower();
  580.     
  581.         EmitInstruction(&mySymbol,-1);
  582.  
  583. #ifdef DEBUGPARSER
  584.         if(mySymbol.kind == kLexMultiply)    printf("* ");
  585.         else
  586.         if(mySymbol.kind == kLexModulo)     printf("% ");
  587.         else                                printf("/ ");
  588. #endif
  589.     }
  590. }
  591.  
  592. void    ParseExpr()
  593. {
  594.     LexSymbol    mySymbol;
  595.     
  596.     ParseTerm();
  597.     
  598.     while(    parserVar.lookahead.kind == kLexPlus ||
  599.             parserVar.lookahead.kind == kLexMinus)
  600.     {    mySymbol.kind = parserVar.lookahead.kind;
  601.  
  602.         LexMatch(parserVar.lookahead.kind);
  603.         ParseTerm();
  604.         EmitInstruction(&mySymbol,-1);
  605.  
  606. #ifdef DEBUGPARSER
  607.         if(mySymbol.kind == kLexPlus)    printf("+ ");
  608.         else                            printf("- ");
  609. #endif
  610.     }
  611. }
  612. void    ParseMinMax()
  613. {
  614.     LexSymbol    mySymbol;
  615.     
  616.     ParseExpr();
  617.     
  618.     while(    parserVar.lookahead.kind == kLexMin ||
  619.             parserVar.lookahead.kind == kLexMax)
  620.     {    mySymbol.kind = parserVar.lookahead.kind;
  621.  
  622.         LexMatch(parserVar.lookahead.kind);
  623.         ParseExpr();
  624.         EmitInstruction(&mySymbol,-1);
  625.  
  626. #ifdef DEBUGPARSER
  627.         if(mySymbol.kind == kLexMin)    printf("min ");
  628.         else                            printf("max ");
  629. #endif
  630.     }
  631. }
  632.  
  633.  
  634. void    ParseCompare()
  635. {
  636.     LexSymbol    mySymbol;
  637.     
  638.     ParseMinMax();
  639.     
  640.     while(    parserVar.lookahead.kind == kLexGt ||
  641.             parserVar.lookahead.kind == kLexEq ||
  642.             parserVar.lookahead.kind == kLexLt)
  643.     {    mySymbol.kind = parserVar.lookahead.kind;
  644.  
  645.         LexMatch(parserVar.lookahead.kind);
  646.         ParseMinMax();
  647.         EmitInstruction(&mySymbol,-1);
  648.  
  649. #ifdef DEBUGOUTPUT
  650.         if(mySymbol.kind == kLexGt    )        printf("> ");
  651.         else if(mySymbol.kind == kLexLt)    printf("< ");
  652.         else                                printf("= ");
  653. #endif
  654.     }
  655. }
  656.  
  657. void    ParseStatement(
  658.     LexSymbol    *statement)
  659. {
  660.     if(parserVar.lookahead.kind == kLexVariable)
  661.     {    *statement = parserVar.lookahead;
  662.         
  663.         LexMatch(parserVar.lookahead.kind);
  664.         if(parserVar.lookahead.kind == kLexEq)
  665.         {
  666.             LexMatch(parserVar.lookahead.kind);
  667.  
  668.             if(statement->value.token > lastVariable)
  669.             {    lastVariable = statement->value.token;
  670.                 CreateVariable(lastVariable);
  671.             }
  672.             
  673.             ParseCompare();
  674.             statement->kind = kAssignment;
  675.             EmitInstruction(statement, -1);
  676.             DEBUGPAR(printf("Store to var #%ld ", statement->value.token);)
  677.         }
  678.         else
  679.         {    parserVar.lookahead.kind = kParseError;
  680.         }
  681.     }
  682.     else
  683.     if(parserVar.lookahead.kind == kLexLevel)
  684.     {    *statement = parserVar.lookahead;
  685.         
  686.         LexMatch(parserVar.lookahead.kind);
  687.         if(parserVar.lookahead.kind == kLexConstant)
  688.         {    statement->value.level = parserVar.lookahead.value.floating;
  689.             DEBUGPAR(printf("Start of level info for level #%3.0lf ", parserVar.lookahead.value.floating);)
  690.             LexMatch(parserVar.lookahead.kind);
  691.         }
  692.         else
  693.         {    parserVar.lookahead.kind = kParseError;
  694.         }
  695.     }
  696.     else    parserVar.lookahead.kind = kParseError;
  697. }
  698.  
  699. void    SetupCompiler(
  700.     StringPtr theInput)
  701. {
  702.     parserVar.input = theInput;
  703.     parserVar.output = NewHandle(0);
  704.     parserVar.realSize = 0;
  705.     parserVar.logicalSize = 0;
  706.     parserVar.stackDepth = 0;
  707.     parserVar.stackMax = 0;
  708.  
  709. }
  710.  
  711. void    WriteVariable(
  712.     long    token,
  713.     double    value)
  714. {
  715.     variableValue    *theVar;
  716.     double            temp;
  717.     
  718.     theVar = variableBase->GetEntryPointer(token);
  719.     if(theVar)
  720.     {    theVar->calcLevel = currentLevel;
  721.         theVar->value = value;
  722.     }
  723.  
  724. }
  725. double    EvalVariable(
  726.     long    token)
  727. {
  728.     variableValue    *theVar;
  729.     double            temp;
  730.     
  731.     theVar = variableBase->GetEntryPointer(token);
  732.     if(theVar->calcLevel != currentLevel)
  733.     {    LexSymbol    *theProgram;
  734.     
  735.         theVar->calcLevel = currentLevel;
  736.         theProgram = programBase->GetEntryPointer(token);
  737.         if(theProgram)
  738.         {    while(theProgram->kind != kAssignment)
  739.             {    switch(theProgram->kind)
  740.                 {    case kLexConstant:
  741.                         *(++stackP) = theProgram->value.floating;
  742.                         break;
  743.                     case kLexVariable:
  744.                         temp = EvalVariable(theProgram->value.token);
  745.                         *(++stackP) = temp;
  746.                         break;
  747.                     case kLexPlus:        stackP[-1] += stackP[0];    stackP--;    break;
  748.                     case kLexMinus:        stackP[-1] -= stackP[0];    stackP--;    break;
  749.                     case kLexMultiply:    stackP[-1] *= stackP[0];    stackP--;    break;
  750.                     case kLexDivide:    stackP[-1] /= stackP[0];    stackP--;    break;
  751.  
  752.                     case kLexGt:        stackP[-1] = stackP[-1] > stackP[0];    stackP--;    break;
  753.                     case kLexLt:        stackP[-1] = stackP[-1] < stackP[0];    stackP--;    break;
  754.                     case kLexEq:        stackP[-1] = stackP[-1] == stackP[0];    stackP--;    break;
  755.                     
  756.                     case kLexPower:        stackP[-1] = pow(stackP[-1], stackP[0]);stackP--;    break;
  757.                     
  758.                     case kLexMin:
  759.                             if(stackP[-1] < stackP[0])    stackP[-1] = stackP[0];
  760.                             stackP--;
  761.                             break;
  762.                     case kLexMax:
  763.                             if(stackP[-1] > stackP[0])    stackP[-1] = stackP[0];
  764.                             stackP--;
  765.                             break;
  766.  
  767.                     case kLexModulo:
  768.                         stackP[-1] = fmod(stackP[-1], stackP[0]);
  769.                         stackP--;
  770.                         break;
  771.                     case kUnaryMinus:    stackP[0] = -stackP[0];        break;
  772.                     case kLexAbs:
  773.                         if(stackP[0] < 0)
  774.                             stackP[0] = -stackP[0];
  775.                         break;
  776.                     case kLexFun0:
  777.                         *(++stackP) = ((unsigned int)Random()) /65536.0;
  778.                         break;
  779.                     case kLexFun1:
  780.                         switch(theProgram->value.token)
  781.                         {    
  782.                             case kSinKey:    *stackP = sin(*stackP);                break;
  783.                             case kCosKey:    *stackP = cos(*stackP);                break;
  784.                             case kRoundKey:    *stackP = floor(*stackP+0.5);        break;
  785.                             case kIntKey:    *stackP = floor(*stackP);            break;
  786.                         }
  787.                         break;
  788.  
  789.                 }
  790.                 theProgram++;
  791.             }
  792.             theVar->value = *(stackP--);
  793.         }
  794.     }
  795.     
  796.     return    theVar->value;
  797. }
  798.  
  799. void    LoadProgram()
  800. {
  801.     OSErr    err;
  802.     short    ref;
  803.     long    preSize, postSize, wholeSize;
  804.     
  805.     theScript = GetResource('TEXT',2128);
  806.     DetachResource(theScript);
  807.     
  808.     preSize = GetHandleSize(theScript);
  809.     
  810.     err = FSOpen("\pArashi Script", 0, &ref);
  811.  
  812.     if(err != noErr)
  813.     {    Handle    postScript;
  814.     
  815.         postScript = GetResource('TEXT',2129);
  816.         postSize = GetHandleSize(postScript);
  817.         wholeSize = postSize + preSize;
  818.         HandAndHand(postScript, theScript);
  819.         ReleaseResource(postScript);
  820.     }
  821.     else
  822.     {    
  823.     
  824.         GetEOF(ref, &postSize);
  825.         wholeSize = postSize + GetHandleSize(theScript);
  826.         SetHandleSize(theScript,wholeSize);
  827.         HLock(theScript);
  828.         if(GetHandleSize(theScript) == wholeSize)
  829.         {    FSRead(ref, &postSize, *theScript+wholeSize-postSize);
  830.         }
  831.         FSClose(ref);
  832.     }
  833.     HUnlock(theScript);
  834.     SetHandleSize(theScript, wholeSize+1);
  835.     HLock(theScript);
  836.     (*theScript)[wholeSize] = 0;    //    Append a NULL to terminate the script.
  837. }
  838.  
  839. void    LoadLevel(
  840.     short    whichLevel)
  841. {
  842.     LexSymbol    statement;
  843.  
  844.     currentLevel = whichLevel;
  845.     
  846.     if(fromLevel > currentLevel)
  847.     {    ResetVariables();
  848.         SetupCompiler((StringPtr)*theScript);
  849.         LexRead(&parserVar.lookahead);
  850.         fromLevel = -1;
  851.         upToLevel = -1;
  852.     }
  853.     
  854.     while(whichLevel >= upToLevel)
  855.     {    ParseStatement(&statement);
  856.         SetHandleSize(parserVar.output, parserVar.logicalSize);
  857.  
  858.         if(parserVar.lookahead.kind == kParseError)
  859.         {
  860.             DEBUGPAR(printf(" ** Parse Error **\n");)
  861.             upToLevel = 32000;
  862.         }
  863.         else
  864.         {    DEBUGPAR(printf("\n");)
  865.             if(statement.kind == kAssignment)
  866.             {    programBase->WriteHandle(statement.value.token, parserVar.output);
  867.             }
  868.             else
  869.             if(statement.kind == kLexLevel)
  870.             {    fromLevel = upToLevel;
  871.                 upToLevel = statement.value.level;
  872.             }
  873.         }
  874.         DisposHandle(parserVar.output);
  875.         SetupCompiler(parserVar.input);
  876.         
  877.         if(parserVar.lookahead.kind == kLexEof)
  878.         {    upToLevel = 32000;
  879.         }
  880.     }
  881.  
  882.     WriteVariable(    kVarLevelNumber, (double) currentLevel);
  883. }
  884. void    RunThis(
  885.     StringPtr    script)
  886. {
  887.     LexSymbol    statement;
  888.  
  889.     parserVar.input = script;
  890.     
  891.     SetupCompiler(parserVar.input);
  892.     LexRead(&parserVar.lookahead);
  893.  
  894.     do
  895.     {    ParseStatement(&statement);
  896.         SetHandleSize(parserVar.output, parserVar.logicalSize);
  897.  
  898.         if(parserVar.lookahead.kind == kParseError)
  899.         {    DEBUGPAR(printf(" ** Parse Error **\n");)
  900.         }
  901.         else
  902.         {    if(statement.kind == kAssignment)
  903.             {    programBase->WriteHandle(statement.value.token, parserVar.output);
  904.                 programBase->Lock();
  905.                 currentLevel++;
  906.                 DEBUGPAR(printf(" ==> %lf\n", EvalVariable(statement.value.token));)
  907.                 programBase->Unlock();
  908.             }
  909.             else
  910.             if(statement.kind == kLexLevel)
  911.             {    fromLevel = upToLevel;
  912.                 upToLevel = statement.value.level;
  913.                 DEBUGPAR(printf("\n");)
  914.             }
  915.         }
  916.         DisposHandle(parserVar.output);
  917.         SetupCompiler(parserVar.input);
  918.         
  919.     } while(!(    parserVar.lookahead.kind == kLexEof ||
  920.                 parserVar.lookahead.kind == kParseError));
  921.  
  922. }
  923.  
  924. void    AllocParser()
  925. {
  926.     InitSymbols();
  927.     stackP = (double *)NewPtr(sizeof(double) * 256);
  928.  
  929.     LoadProgram();
  930.  
  931. }
  932.  
  933. #ifdef DEBUGPARSER
  934. void    main()
  935. {
  936.     unsigned    char    dummystring[128];
  937.     unsigned    char    *ditto;
  938.     int                    numChars;
  939.     short                i;
  940.     short                j;
  941.  
  942.     printf("Enter expressions and see if I can parse them.\n");
  943.  
  944.     InitSymbols();
  945.     stackP = (double *)NewPtr(sizeof(double) * 256);
  946.     
  947.     LoadProgram();
  948.     
  949.     for(i=1;i<15;i++)
  950.     {    LoadLevel(i);
  951.         programBase->Lock();
  952.         
  953.         printf("Level %4d   Flippercount: %d\n", currentLevel, (int)EvalVariable(kVarFlipperCount));
  954.         programBase->Unlock();
  955.     }
  956.  
  957.  
  958.     do
  959.     {    ditto=(void *)fgets((char *)dummystring,127,stdin);
  960.         RunThis(dummystring);
  961.  
  962.     } while(ditto);
  963. }
  964. #endif